/**
 * Midway v1.5.7
 * (c) 2017 Jorson WHY
 * @license MIT
 */
(function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('jquery')) :
  typeof define === 'function' && define.amd ? define(['jquery'], factory) :
  (factory(global.jQuery));
}(this, (function (jQuery) { 'use strict';

jQuery = 'default' in jQuery ? jQuery['default'] : jQuery;

function stringPolyFill() {
    String.prototype.trim = function (char, type) {
        if (char) {
            if (type === 'left') {
                return this.replace(new RegExp('^\\' + char + '+', 'g'), '');
            } else if (type === 'right') {
                return this.replace(new RegExp('\\' + char + '+$', 'g'), '');
            }
            return this.replace(new RegExp('^\\' + char + '+|\\' + char + '+$', 'g'), '');
        }
        return this.replace(/^\s+|\s+$/g, '');
    };
    if (typeof String.prototype.insert !== 'function') {
        String.prototype.insert = function (index, string) {
            if (index > 0) return this.substring(0, index) + string + this.substring(index, this.length);else return string + this;
        };
    }
}

function arrayPolyFill() {
    if (typeof Array.prototype.from !== 'function') {
        Array.prototype.from = function () {
            var toStr = Object.prototype.toString;
            var isCallable = function isCallable(fn) {
                return typeof fn === 'function' || toStr.call(fn) === '[object Function]';
            };
            var toInteger = function toInteger(value) {
                var number = Number(value);
                if (isNaN(number)) {
                    return 0;
                }
                if (number === 0 || !isFinite(number)) {
                    return number;
                }
                return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number));
            };
            var maxSafeInteger = Math.pow(2, 53) - 1;
            var toLength = function toLength(value) {
                var len = toInteger(value);
                return Math.min(Math.max(len, 0), maxSafeInteger);
            };
            return function from(arrayLike /*, mapFn, thisArg */) {
                var C = this;
                var items = Object(arrayLike);
                if (arrayLike === null) {
                    throw new TypeError('Array.from requires an array-like object - not null or undefined');
                }
                var mapFn = arguments.length > 1 ? arguments[1] : void undefined;
                var T = void 0;
                if (typeof mapFn !== 'undefined') {
                    if (!isCallable(mapFn)) {
                        throw new TypeError('Array.from: when provided, the second argument must be a function');
                    }
                    if (arguments.length > 2) {
                        T = arguments[2];
                    }
                }
                var len = toLength(items.length),
                    A = isCallable(C) ? Object(new C(len)) : new Array(len),
                    k = 0,
                    kValue = void 0;
                while (k < len) {
                    kValue = items[k];
                    if (mapFn) {
                        A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k);
                    } else {
                        A[k] = kValue;
                    }
                    k += 1;
                }
                A.length = len;
                return A;
            };
        }();
    }

    if (typeof Array.prototype.forEach !== 'function') {
        Array.prototype.forEach = function (callback, thisObj) {
            var T = void 0,
                k = void 0;
            if (this === null) {
                throw new TypeError(' this is null or not defined');
            }
            var O = Object(this),
                len = O.length >>> 0;
            if (typeof callback !== "function") {
                throw new TypeError(callback + ' is not a function');
            }
            if (arguments.length > 1) {
                T = thisObj;
            }
            k = 0;
            while (k < len) {
                var kValue = void 0;
                if (k in O) {
                    kValue = O[k];
                    callback.call(T, kValue, k, O);
                }
                k++;
            }
        };
    }
    //修正NodeList
    if (typeof NodeList.prototype.forEach !== 'function') {
        NodeList.prototype.forEach = Array.prototype.forEach;
    }

    if (typeof Array.prototype.each !== 'function') {
        Array.prototype.each = function (callback, thisObj) {
            var T = void 0,
                k = void 0;

            if (this === null) {
                throw new TypeError(' this is null or not defined');
            }
            var O = Object(this),
                len = O.length >>> 0;
            if (typeof callback !== "function") {
                throw new TypeError(callback + ' is not a function');
            }
            if (arguments.length > 1) {
                T = thisObj;
            }
            k = 0;
            while (k < len) {
                var kValue = void 0;
                if (k in O) {
                    kValue = O[k];
                    callback.call(T, kValue, k, O);
                }
                k++;
            }
        };
    }

    if (typeof Array.prototype.isArray !== 'function') {
        Array.prototype.isArray = function (arg) {
            return Object.prototype.toString.call(arg) === '[object Array]';
        };
    }

    if (typeof Array.prototype.includes !== 'function') {
        Array.prototype.includes = function (searchElement, fromIndex) {
            'use strict';

            if (this === null) {
                throw new TypeError('"this" is null or not defined');
            }
            var o = Object(this),
                len = o.length >>> 0;
            if (len === 0) {
                return false;
            }
            var n = fromIndex | 0;
            var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
            while (k < len) {
                if (o[k] === searchElement) {
                    return true;
                }
                k++;
            }
            return false;
        };
    }

    if (typeof Array.prototype.find !== 'function') {
        Array.prototype.find = function (predicate) {
            'use strict';

            if (this === null) {
                throw new TypeError('Array.prototype.find called on null or undefined');
            }
            if (typeof predicate !== 'function') {
                throw new TypeError('predicate must be a function');
            }
            var list = Object(this),
                length = list.length >>> 0,
                thisArg = arguments[1],
                value = void 0;

            for (var i = 0; i < length; i++) {
                value = list[i];
                if (predicate.call(thisArg, value, i, list)) {
                    return value;
                }
            }
            return undefined;
        };
    }

    if (typeof Array.prototype.findIndex !== 'function') {
        Array.prototype.findIndex = function (predicate) {
            if (this === null) {
                throw new TypeError('Array.prototype.findIndex called on null or undefined');
            }
            if (typeof predicate !== 'function') {
                throw new TypeError('predicate must be a function');
            }
            var list = Object(this),
                length = list.length >>> 0,
                thisArg = arguments[1],
                value = void 0;

            for (var i = 0; i < length; i++) {
                value = list[i];
                if (predicate.call(thisArg, value, i, list)) {
                    return i;
                }
            }
            return -1;
        };
    }

    if (typeof Array.prototype.compact !== 'function') {
        Array.prototype.compact = function () {
            var index = -1,
                length = this === null ? 0 : this.length,
                resIndex = 0,
                result = [];
            while (++index < length) {
                var value = this[index];
                if (value) {
                    result[resIndex++] = value;
                }
            }
            return result;
        };
    }

    if (typeof Array.prototype.insertOf !== 'function') {
        Array.prototype.insertOf = function (index, value) {
            if (this.length < index) {
                throw Error('index can not big than length!');
            }
            this.splice(index, 0, value);
        };
    }
}

function DOMPolyFill() {
    var polyArray = [Element.prototype, CharacterData.prototype, DocumentType.prototype];
    polyArray.forEach(function (item) {
        if (item.hasOwnProperty('remove')) {
            return;
        }
        Object.defineProperty(item, 'remove', {
            configurable: true,
            enumerable: true,
            writable: true,
            value: function remove() {
                this.parentNode.removeChild(this);
            }
        });
    });
}

function assert(condition, msg) {
    if (condition) throw new Error("[midway] " + msg);
}

var _head = document.head || document.getElementsByTagName("head")[0] || document.documentElement;

var ScriptRender = {
    /**
     * 添加外部的URL引用
     * @param url 外部URL地址
     * @attrs 额外附加在style标签上的属性
     */
    addStyle: function addStyle() {
        var url = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : undefined;
        var attrs = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined;

        assert(url === undefined, "style url is undefined");
        var element = document.createElement('link');
        element.setAttribute('rel', 'stylesheet');
        element.setAttribute('type', 'text/css');
        element.setAttribute('href', url);
        if (attrs !== undefined) {
            for (var key in attrs) {
                script.setAttribute(key, attr[key]);
            }
        }
        _head.appendChild(element);
        return element;
    },
    /**
     * 添加外部Javascript引用
     * @param url 外部JS地址
     * @attrs 额外附加在script标签上的属性
     */
    addJavascript: function addJavascript(url) {
        var attrs = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined;

        assert(url === undefined, "script url is undefined");
        var deferred = $.Deferred(),
            script = document.createElement("script");
        script.type = 'text/javascript';
        script.charset = 'utf-8';
        script.async = true;
        script.src = url;
        if (attrs !== undefined) {
            for (var key in attrs) {
                script.setAttribute(key, attr[key]);
            }
        }
        script.onerror = function () {
            console.error("javascript load failure!, URL=" + url);
            deferred.reject();
        };
        script.onload = script.onreadystatechange = function (_, isAbort) {
            if (isAbort || !script.readyState || /loaded|complete/.test(script.readyState)) {
                script.onload = script.onreadystatechange = null;
                script = null;
                if (!isAbort) {
                    deferred.resolve();
                } else {
                    deferred.reject();
                    console.error("load javascript abort!, URL=" + url);
                }
            }
        };
        _head.appendChild(script);
        return deferred.promise();
    },
    addEmbedStyle: function addEmbedStyle(code) {
        var attrs = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined;

        var element = document.createElement("style");
        if (element.styleSheet) {
            element.styleSheet.cssText = code;
        } else {
            element.innerHTML = code;
        }
        if (attrs !== undefined) {
            for (var key in attrs) {
                element.setAttribute(key, attrs[key]);
            }
        }
        _head.appendChild(element);
        return element;
    },
    addEmbedScript: function addEmbedScript(code) {
        var attrs = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined;

        var element = document.createElement("script");
        element.setAttribute("language", "Javascript");
        element.text = code;
        if (attrs !== undefined) {
            for (var key in attrs) {
                element.setAttribute(key, attrs[key]);
            }
        }
        _head.appendChild(element);
        return element;
    },
    /**
     * 检查外部样式是否引用
     * @param predicate 移除样式的依据, 可以是URL或函数
     * @returns {boolean} 引用情况
     */
    checkStyle: function checkStyle(predicate) {
        var exists = false;
        if (typeof predicate === 'string') {
            $.each(document.head.childNodes, function (index, item) {
                if (item.nodeName === 'LINK' && item.attributes['href'].value === predicate) {
                    exists = true;
                    return false;
                }
            });
        } else if (typeof predicate === 'function') {
            $.each(document.head.childNodes, function (index, item) {
                if ((item.nodeName === 'LINK' || item.nodeName === 'STYLE') && predicate.call(undefined, item)) {
                    exists = true;
                    return false;
                }
            });
        }
        return exists;
    },
    /**
     * 移除外接样式
     * @param predicate 移除样式的依据, 可以是URL或函数
     */
    removeStyle: function removeStyle(predicate) {
        if (typeof predicate === 'string') {
            var url = predicate;
            document.head.childNodes.forEach(function (item) {
                if (item.nodeName === 'LINK' && item.attributes['href'].value === url) {
                    _head.removeChild(item);
                }
            });
        } else if (typeof predicate === 'function') {
            document.head.childNodes.forEach(function (item) {
                if (item.nodeName === 'LINK' && predicate.call(undefined, item)) {
                    _head.removeChild(item);
                }
            });
        }
    },
    removeStyleElement: function removeStyleElement() {
        var element = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : undefined;

        assert(element === undefined, "style element is undefined");
        _head.removeChild(element);
        element = null;
    }
};

var _arguments = arguments;
var supportFunction = {
    runSequence: function runSequence(fnConfigs, name) {
        var $promise = $.Deferred().resolve();
        var runIndex = void 0;

        fnConfigs.forEach(function (fnconfig, index) {
            if ($.isFunction(fnconfig.fn)) {
                $promise = $promise.then(function () {
                    try {
                        runIndex = index;
                        var callArgs = fnconfig.args || _arguments;
                        if (fnconfig.isAppendArgs === true) {
                            callArgs = Array.prototype.slice.call(_arguments, 0);
                            callArgs = callArgs.concat(fnConfig.args);
                        }
                        return fnconfig.fn.apply(fnconfig.scope || window, callArgs);
                    } catch (e) {
                        return $.Deferred(function (deferred) {
                            deferred.reject(e);
                        });
                    }
                }, function (message) {
                    return message;
                });
            }
        });

        return $promise.fail(function (e) {
            console.error("execute %s, number of %d error", name || "task", ++runIndex, e || "");
        });
    },

    execute: function execute(instance, injections, args, isCheck) {
        //参数整理
        var singleExecuteName = '';
        var result = {};
        if (typeof injections === 'string') {
            singleExecuteName = injections;
            injections = {};
            injections[singleExecuteName] = args || [];
        }
        if (instance) {
            for (var name in injections) {
                var fn = instance[name];
                if ($.isFunction(fn)) {
                    var params = injections[name];
                    var callMethod = $.isArray(params) ? 'apply' : 'call';
                    result[name] = Function.prototype[callMethod].call(fn, instance, params);
                } else if (isCheck === true) {
                    logger.error("不存在[" + name + ']方法');
                }
            }
        }
        return singleExecuteName ? result[singleExecuteName] : result;
    },

    createDelegate: function createDelegate(fn, args, isAppendArgs, scope, exceptionHandler) {
        return function () {
            //如果创建的时候没有输入参数，使用调用的参数
            var callArgs = args || _arguments;
            if (isAppendArgs === true) {
                //arguments数组化
                callArgs = Array.prototype.slice.call(_arguments, 0);
                callArgs = callArgs.concat(args);
            }
            try {
                return fn.apply(scope || window, callArgs);
            } catch (e) {
                if ($.isFunction(exceptionHandler)) {
                    return exceptionHandler(e);
                } else {
                    throw e;
                }
            }
        };
    },

    defer: function defer(millis, fn, args, appendArgs, scope) {
        var callFn = functionHelper.createDelegate(fn, args, appendArgs, scope);
        if (millis > 0) {
            return window.setTimeout(callFn, millis);
        }
        //直接调用，返回0的timerId
        callFn();
        return 0;
    },

    createPromiseThen: function createPromiseThen(deferred, fn, args, isAppendArgs, scope) {
        if (!$.isFunction(deferred.reject)) {
            scope = isAppendArgs;
            isAppendArgs = args;
            args = fn;
            fn = deferred;
            deferred = $.Deferred();
        }
        return supportFunction.createDelegate(fn, args, isAppendArgs, scope, function (e) {
            deferred.reject(e);
            return deferred.promise();
        });
    },

    isEmptyObject: function isEmptyObject(obj) {
        for (var name in obj) {
            return false;
        }
        return true;
    },

    isOwnEmptyObject: function isOwnEmptyObject(obj) {
        for (var name in obj) {
            if (obj.hasOwnProperty(name)) {
                return false;
            }
        }
        return true;
    },

    hasProp: function hasProp(obj, prop) {
        return Object.prototype.hasOwnProperty.call(obj, prop);
    },

    getOwn: function getOwn(obj, prop) {
        return obj && Object.prototype.hasOwnProperty.call(obj, prop) && obj[prop];
    },

    defineProperty: function defineProperty(obj, key, value) {
        var config = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : { configurable: false, enumerable: false, writable: false };

        Object.defineProperty(obj, key, {
            configurable: config.configurable || false,
            enumerable: config.enumerable || false,
            writable: config.writable || false,
            value: value
        });
    }
};

var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
  return typeof obj;
} : function (obj) {
  return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};











var classCallCheck = function (instance, Constructor) {
  if (!(instance instanceof Constructor)) {
    throw new TypeError("Cannot call a class as a function");
  }
};

var createClass = function () {
  function defineProperties(target, props) {
    for (var i = 0; i < props.length; i++) {
      var descriptor = props[i];
      descriptor.enumerable = descriptor.enumerable || false;
      descriptor.configurable = true;
      if ("value" in descriptor) descriptor.writable = true;
      Object.defineProperty(target, descriptor.key, descriptor);
    }
  }

  return function (Constructor, protoProps, staticProps) {
    if (protoProps) defineProperties(Constructor.prototype, protoProps);
    if (staticProps) defineProperties(Constructor, staticProps);
    return Constructor;
  };
}();









var inherits = function (subClass, superClass) {
  if (typeof superClass !== "function" && superClass !== null) {
    throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
  }

  subClass.prototype = Object.create(superClass && superClass.prototype, {
    constructor: {
      value: subClass,
      enumerable: false,
      writable: true,
      configurable: true
    }
  });
  if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
};











var possibleConstructorReturn = function (self, call) {
  if (!self) {
    throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
  }

  return call && (typeof call === "object" || typeof call === "function") ? call : self;
};

var Loader = function () {
    function Loader(getKey, createLoadPromise, context) {
        classCallCheck(this, Loader);

        this.promises = {};
        this.getKey = getKey;
        this.context = context || window;
        this.createLoadPromise = createLoadPromise;
    }

    createClass(Loader, [{
        key: "load",
        value: function load(loaders) {
            var _this = this;

            var loaderList = Array.prototype.isArray(loaders) ? loaders : Array.prototype.slice.call(arguments, 1);
            var _promises = [];
            loaderList.forEach(function (loader) {
                var key = _this.getKey(loader);
                var _promise = _this.promises[key] || (_this.promises[key] = _this.createLoadPromise.call(_this.context, loader));
                _promises.push(_promise);
            });
            return $.when.apply($, _promises);
        }
    }]);
    return Loader;
}();

var BasicManager = function () {
    function BasicManager() {
        classCallCheck(this, BasicManager);

        this.collection = {};
    }

    createClass(BasicManager, [{
        key: "add",
        value: function add(name, item) {
            assert(item === undefined, "manage item can't NULL!");
            if (this.collection[name] === undefined) {
                this.collection[name] = item;
            }
        }
    }, {
        key: "get",
        value: function get$$1(name) {
            if (this.collection[name]) {
                return this.collection[name];
            }
            return undefined;
        }
    }, {
        key: "exists",
        value: function exists(name) {
            return !(this.collection[name] === undefined);
        }
    }, {
        key: "remove",
        value: function remove(name) {
            if (this.collection[name]) {
                this.beforeRemove(this.collection[name]);
                this.collection[name] = null;
                delete this.collection[name];
                this.afterRemove();
            }
        }
    }, {
        key: "release",
        value: function release() {
            for (var key in this.collection) {
                delete this.collection[key];
            }
            this.collection = null;
        }
    }, {
        key: "each",
        value: function each(fn) {
            if (typeof fn !== 'function') {
                return;
            }
            for (var key in this.collection) {
                fn.call(this, key, this.collection[key]);
            }
        }
    }, {
        key: "beforeRemove",
        value: function beforeRemove(item) {}
    }, {
        key: "afterRemove",
        value: function afterRemove() {}
    }]);
    return BasicManager;
}();

var ScriptLibraryManager = function (_BasicManager) {
    inherits(ScriptLibraryManager, _BasicManager);

    function ScriptLibraryManager() {
        var _ret;

        classCallCheck(this, ScriptLibraryManager);

        if (!ScriptLibraryManager.instance) {
            var _this = possibleConstructorReturn(this, (ScriptLibraryManager.__proto__ || Object.getPrototypeOf(ScriptLibraryManager)).call(this));

            _this._scriptSettings = [];
            ScriptLibraryManager.instance = _this;
        }
        return _ret = ScriptLibraryManager.instance, possibleConstructorReturn(_this, _ret);
    }

    createClass(ScriptLibraryManager, [{
        key: "ScriptSettings",
        get: function get$$1() {
            return this._scriptSettings;
        },
        set: function set$$1(setting) {
            this._scriptSettings = setting;
        }
    }]);
    return ScriptLibraryManager;
}(BasicManager);

var scriptLibraryManager = new ScriptLibraryManager();

var ThirdLibraryLoader = function () {
    function ThirdLibraryLoader() {
        classCallCheck(this, ThirdLibraryLoader);

        this._loader = undefined;
        this._defMappings = {};
    }

    /**
     * 创建第三方库的加载器
     * @returns {*}
     */


    createClass(ThirdLibraryLoader, [{
        key: "create",
        value: function create() {
            if (this._loader === undefined) {
                this._loader = new Loader(this._getKey, this._createLoadPromise, this);
            }
            return this._loader;
        }
    }, {
        key: "_getKey",
        value: function _getKey(item) {
            return item.name;
        }
    }, {
        key: "_createLoadPromise",
        value: function _createLoadPromise(config) {
            var _this = this;

            var deferred = $.Deferred();
            return deferred.resolve().then(function () {
                return _this._importStyle(config);
            }).then(function () {
                if (config.depends.length === 0) {
                    return _this._importJsLib(config);
                } else {
                    var defList = _this._getDependDef(config.depends);
                    return jQuery.when.apply(_this, defList).done(function () {
                        return _this._importJsLib(config);
                    });
                }
            });
        }
    }, {
        key: "_importJsLib",
        value: function _importJsLib(config) {
            var loadList = [];
            config.scripts.forEach(function (item) {
                loadList.push({
                    fn: ScriptRender.addJavascript,
                    args: [item + "?release=" + config.release]
                });
            });
            if (!supportFunction.hasProp(this._defMappings, config.name)) {
                this._defMappings[config.name] = supportFunction.runSequence(loadList, "Load Javascript Library");
            }
            return this._defMappings[config.name];
        }
    }, {
        key: "_importStyle",
        value: function _importStyle(config) {
            var loadList = [];
            config.styles.forEach(function (item) {
                loadList.push({
                    fn: ScriptRender.addStyle,
                    args: [item + "?release=" + config.release]
                });
            });
            return supportFunction.runSequence(loadList, "Load Style Library");
        }
    }, {
        key: "_getDependDef",
        value: function _getDependDef(deps) {
            var _this2 = this;

            var result = [];
            deps.forEach(function (dep) {
                if (supportFunction.hasProp(_this2._defMappings, dep.name)) {
                    result.push(_this2._defMappings[dep.name]);
                }
            });
            return result;
        }
    }]);
    return ThirdLibraryLoader;
}();

var JsLibLoader = function () {
    var instance = void 0;
    return {
        name: "ThirdLibraryLoader",
        getInstance: function getInstance() {
            if (instance === undefined) {
                instance = new ThirdLibraryLoader();
            }
            return instance;
        },
        findDependScript: function findDependScript(config, loadLibs) {
            var preLoad = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;

            if (config.depends.length === 0) {
                if (!supportFunction.hasProp(loadLibs, config.name)) {
                    JsLibLoader.addToLoadLibs(config, loadLibs, config.autoLoad, preLoad);
                }
            } else {
                config.depends.forEach(function (depend) {
                    if (scriptLibraryManager.exists(depend.name)) {
                        //如果已经添加过
                        var tConfig = scriptLibraryManager.get(depend.name);
                        if (tConfig.depends.length > 0) {
                            JsLibLoader.findDependScript(tConfig, loadLibs);
                        } else {
                            JsLibLoader.addToLoadLibs(tConfig, loadLibs, config.autoLoad, preLoad);
                        }
                    } else {
                        //如果没有被添加过
                        var dependScript = scriptLibraryManager.ScriptSettings.find(function (item) {
                            return item.name === depend.name;
                        });
                        if (!dependScript) {
                            //未能找到依赖脚本库的配置
                            console.warn('Failed to find the configuration of ' + depend.name + ' on which ' + config.name + ' depends');
                        } else {
                            scriptLibraryManager.add(dependScript.name, {
                                name: dependScript.name,
                                autoLoad: dependScript.autoLoad,
                                version: dependScript.version,
                                styles: dependScript.css || [],
                                scripts: dependScript.script || [],
                                depends: dependScript.dependencies || [],
                                loaded: false
                            });
                            var _tConfig = scriptLibraryManager.get(dependScript.name);
                            if (_tConfig.depends.length > 0) {
                                JsLibLoader.findDependScript(_tConfig, loadLibs);
                            } else {
                                JsLibLoader.addToLoadLibs(_tConfig, loadLibs, config.autoLoad, preLoad);
                            }
                        }
                    }
                });
                JsLibLoader.addToLoadLibs(config, loadLibs, config.autoLoad, preLoad);
            }
        },
        addToLoadLibs: function addToLoadLibs(config, loadLibs, autoLoad, preLoad) {
            if (config.loaded === true) {
                return;
            }
            var index = loadLibs.findIndex(function (item) {
                return item.name === config.name;
            });
            if (index === -1) {
                if (preLoad === true && autoLoad === 'true' || preLoad === false) {
                    loadLibs.push(config);
                }
            }
        }
    };
}();

var ModuleManager = function (_BasicManager) {
    inherits(ModuleManager, _BasicManager);

    function ModuleManager() {
        var _ret;

        classCallCheck(this, ModuleManager);

        if (!ModuleManager.instance) {
            var _this = possibleConstructorReturn(this, (ModuleManager.__proto__ || Object.getPrototypeOf(ModuleManager)).call(this));

            _this._bundleConfig = {};
            ModuleManager.instance = _this;
        }
        return _ret = ModuleManager.instance, possibleConstructorReturn(_this, _ret);
    }

    createClass(ModuleManager, [{
        key: "ModuleConfig",
        get: function get$$1() {
            return this._bundleConfig;
        },
        set: function set$$1(config) {
            this._bundleConfig = config;
        }
    }]);
    return ModuleManager;
}(BasicManager);

var moduleManager = new ModuleManager();

var templateRegExp = /\$\{(.+?)\}/g;
var hexDigits = "0123456789abcdefghijklmnopqrstuvwxyz";

var stringUtils = {
    applyTemplate: function applyTemplate(template, attrs) {
        return template.replace(templateRegExp, function ($0, $1) {
            return attrs[$1] || $0;
        });
    },
    createReg: function createReg(array) {
        return array.length ? new RegExp('^(' + array.join("|") + ')$') : /^$/;
    },
    uuid: function uuid(len) {
        var uuids = [];
        for (var i = 0; i < len; i++) {
            uuids[i] = hexDigits.substr(Math.floor(Math.random() * 36), 1);
        }
        return uuids.join('');
    },
    urlJoin: function urlJoin() {
        var input = arguments;
        var options = {};

        if (_typeof(arguments[0]) === 'object') {
            input = arguments[0];
            options = arguments[1] || {};
        }
        input = Array.prototype.compact.call(input);
        var joined = [].splice.call(input, 0).join('/');
        return normalize(joined, options);
    },
    randomWord: function randomWord(randomFlag, min, max) {
        var str = "",
            range = min,
            arr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
        // 随机产生
        if (randomFlag) {
            range = Math.round(Math.random() * (max - min)) + min;
        }
        var pos = -1;
        for (var i = 0; i < range; i++) {
            pos = Math.round(Math.random() * (arr.length - 1));
            str += arr[pos];
        }
        return str;
    }
};

function startWith(str, search) {
    return str.substr(0, search.length) === search;
}

function normalize(str, options) {
    if (startWith(str, 'file://')) {
        str = str.replace(/(\/{0,3})\/*/g, '$1');
    } else {
        str = str.replace(/:\//g, '://');
        str = str.replace(/([^:\s\%\3\A])\/+/g, '$1/');
    }
    str = str.replace(/\/(\?|&|#[^!])/g, '$1');
    str = str.replace(/(\?.+)\?/g, '$1&');
    return str;
}

/**
 * 获取定制播放器的配置信息
 */
function getPlayerConfig(envConfig, code, version, file) {
    var async = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;

    var configPath = void 0;
    if (envConfig.Online === false) {
        configPath = stringUtils.urlJoin(envConfig.ConfigPath || "configuration", file);
    } else {
        //开发环境下
        if (envConfig.RunEnvironment === 'development') {} else {
            if (code === undefined || version === undefined) {
                throw Error("invalid arguments");
            }
            configPath = stringUtils.urlJoin(envConfig.BasePath, 'players', code, version, file);
        }
    }

    return jQuery.ajax({
        url: configPath,
        dataType: 'json',
        method: 'GET',
        cache: false,
        async: async
    });
}

function getScriptConfig(envConfig, scripts, configFiles) {
    var configUrls = [],
        defList = [],
        rootPath = envConfig.Online ? envConfig.BasePath : "ref";
    configFiles.forEach(function (file) {
        if (envConfig.Online === false) {
            configUrls.push(stringUtils.applyTemplate(file, { "ref-path-addon": rootPath }));
        } else {
            configUrls.push(stringUtils.applyTemplate(file, { "ref-path-addon": rootPath }));
        }
    });
    configUrls.forEach(function (url) {
        var def = jQuery.ajax({
            url: url,
            dataType: 'json',
            method: 'GET',
            cache: false,
            async: false
        });
        defList.push(def);
    });

    return jQuery.when.apply(jQuery, defList).done(function () {
        var mergeConfig = {};
        for (var index = 0, len = arguments.length; index < len; index++) {
            if (arguments[index][0] !== undefined) {
                jQuery.extend(true, mergeConfig, arguments[index][0]);
            }
        }
        scripts.forEach(function (script) {
            if (mergeConfig[script.name]) {
                for (var _index = 0, _len = mergeConfig[script.name].css.length; _index < _len; _index++) {
                    var template = mergeConfig[script.name].css[_index];
                    mergeConfig[script.name].css[_index] = stringUtils.applyTemplate(template, { "ref-path-addon": rootPath });
                }
                for (var _index2 = 0, _len2 = mergeConfig[script.name].script.length; _index2 < _len2; _index2++) {
                    var _template = mergeConfig[script.name].script[_index2];
                    mergeConfig[script.name].script[_index2] = stringUtils.applyTemplate(_template, { "ref-path-addon": rootPath });
                }
                script.css = mergeConfig[script.name].css;
                script.script = mergeConfig[script.name].script;
                script.dependencies = mergeConfig[script.name].dependencies;
            }
        });
    });
}

var PreLoader = function () {
    function PreLoader() {
        classCallCheck(this, PreLoader);
    }

    /**
     * 加载预加载配置信息
     */


    createClass(PreLoader, [{
        key: "load",
        value: function load(config) {
            var def = jQuery.Deferred();
            //设置Bundle的配置, 可以从presenters和components获取
            if (supportFunction.hasProp(config, 'presenters')) {
                var temp = this._fixBundleConfig(supportFunction.getOwn(config, 'presenters'), 'ref/presenters');
                jQuery.extend(moduleManager.ModuleConfig, temp);
            }
            if (supportFunction.hasProp(config, 'components')) {
                var _temp = this._fixBundleConfig(supportFunction.getOwn(config, 'components'), 'ref/modules');
                jQuery.extend(moduleManager.ModuleConfig, _temp);
            }

            //整理待加载脚本的顺序
            var loadLibs = [],
                configFiles = [];
            if (supportFunction.hasProp(config, 'mScript') && supportFunction.hasProp(config, 'script')) {
                for (var key in config['mScript']) {
                    configFiles.push(config['mScript'][key].href);
                }
                var scriptSettings = supportFunction.getOwn(config, 'script');
                getScriptConfig(MidwayConfig, scriptSettings, configFiles).done(function () {
                    scriptLibraryManager.ScriptSettings = scriptSettings;
                    scriptSettings.forEach(function (scriptConfig) {
                        var libName = scriptConfig.name;
                        var config = void 0;
                        if (!scriptLibraryManager.exists(libName)) {
                            scriptLibraryManager.add(libName, {
                                name: libName,
                                autoLoad: scriptConfig.autoLoad,
                                version: scriptConfig.version,
                                styles: scriptConfig.css || [],
                                scripts: scriptConfig.script || [],
                                depends: scriptConfig.dependencies || [],
                                release: scriptConfig.releaseNum || "000000",
                                loaded: false
                            });
                        }
                        config = scriptLibraryManager.get(libName);
                        JsLibLoader.findDependScript(config, loadLibs, true);
                    });
                    var loader = JsLibLoader.getInstance().create();
                    loader.load(loadLibs).done(function () {
                        loadLibs.forEach(function (item) {
                            item.loaded = true;
                        });
                        def.resolve();
                    });
                }).fail(function () {
                    console.error('Load preload configured error');
                    def.reject();
                });
            } else {
                def.resolve();
            }
            return def.promise();
        }
    }, {
        key: "_fixBundleConfig",
        value: function _fixBundleConfig(config, path) {
            var moduleConfig = {};
            if (MidwayConfig.BundlePath !== 'presenters' && MidwayConfig.BundlePath !== 'modules') {
                path = MidwayConfig.BundlePath;
            }
            for (var key in config) {
                var pConfig = config[key];
                if (!supportFunction.hasProp(moduleConfig, key)) {
                    var fileName = key + '.dist.js';
                    var moduleUrl = MidwayConfig.Online ? stringUtils.urlJoin(MidwayConfig.BasePath, path, key, pConfig.version, fileName, "?release=" + pConfig.releaseNum || MidwayConfig.PlayerReleaseNumber) : MidwayConfig.RunEnvironment === 'development' ? stringUtils.urlJoin(MidwayConfig.BasePath, path, key, "dist", fileName, "?release=" + pConfig.releaseNum || MidwayConfig.PlayerReleaseNumber) : stringUtils.urlJoin(MidwayConfig.BasePath, path, key, fileName, "?release=" + pConfig.releaseNum || MidwayConfig.PlayerReleaseNumber);
                    moduleConfig[key] = {
                        href: moduleUrl,
                        version: pConfig.version
                    };
                }
            }
            return moduleConfig;
        }
    }]);
    return PreLoader;
}();

var WebEventBus = function () {
    function WebEventBus() {
        classCallCheck(this, WebEventBus);

        this.listeners = [];
    }

    createClass(WebEventBus, [{
        key: 'addEventListener',
        value: function addEventListener(name, callback) {
            var scope = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : window;

            var argsLength = 4;
            var args = arguments.length > argsLength ? Array.prototype.slice.call(arguments, argsLength) : [];
            var listeners = this.listeners[name] || (this.listeners[name] = []);
            listeners.push({
                scope: scope,
                callback: callback,
                args: args
            });
        }

        /**
         * 移除特定事件监听器
         * @param name 监听事件的名称
         * @param callback 回调函数
         * @param scope 回到上下文
         */

    }, {
        key: 'removeEventListener',
        value: function removeEventListener(name, callback) {
            var scope = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : window;

            if (typeof this.listeners.name === 'undefined') {
                return;
            }

            var newArray = [];
            for (var index = 0, len = this.listeners[name].length; index < len; index++) {
                var listener = this.listeners[name][index];
                if (!(listener.scope === scope && listener.callback === callback)) {
                    newArray.push(listener);
                }
            }
            this.listeners[name] = newArray;
        }

        /**
         * 检查是否存在指定的事件监听器
         * @param name 监听器名称
         * @param callback 回调函数
         * @param scope 执行上下文
         * @returns {boolean} 监听器的存在性
         */

    }, {
        key: 'hasEventListener',
        value: function hasEventListener(name, callback) {
            var scope = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : window;

            if (typeof this.listeners.name === 'undefined') {
                return false;
            }
            for (var index = 0, len = this.listeners[name].length; index < len; index++) {
                var listener = this.listeners[name][index];
                if ((scope ? listener.scope === scope : true) && listener.callback === callback) {
                    return true;
                }
            }
            return false;
        }

        /**
         * 分发事件
         * @param name 事件名称
         */

    }, {
        key: 'dispatch',
        value: function dispatch(name) {
            var args = arguments.length > 1 ? Array.prototype.slice.call(arguments, 1) : [];
            args.push(name);
            if (this.listeners && this.listeners[name]) {
                this.listeners[name].forEach(function (listener) {
                    callListener(listener, args);
                });
            }
        }
    }]);
    return WebEventBus;
}();

//调用监听器方法


function callListener(listener, args) {
    listener.callback.apply(listener.scope || window, args.concat(listener.args));
}

var EventScope = {
    GlobalBundle: 'global_bundle',
    CurrentBundle: 'current_bundle'
};

var EventType = {
    WebEvent: 'web_event',
    NativeEvent: 'native_event',
    PPTEvent: 'ppt_native_event'
};

var EventBus = function () {
    function EventBus(webEventBus, nativeEventBus) {
        classCallCheck(this, EventBus);

        this._webEventBus = webEventBus;
        this._nativeEventBus = nativeEventBus;
    }

    createClass(EventBus, [{
        key: "addEventListener",
        value: function addEventListener(name, type, callback) {
            var scope = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : window;

            switch (type) {
                case EventType.WebEvent:
                    this._webEventBus.addEventListener(name, callback, scope);
                    break;
                case EventType.NativeEvent:
                case EventType.PPTEvent:
                    if (this._nativeEventBus) {
                        this._nativeEventBus.registerListener(name, callback, scope);
                    }
                    break;
                default:
                    console.warn('Unsupported event type');
                    break;
            }
        }
    }, {
        key: "removeEventListener",
        value: function removeEventListener(name, type) {
            switch (type) {
                case EventType.WebEvent:
                    break;
                case EventType.NativeEvent:
                case EventType.PPTEvent:
                    break;
                default:
                    console.warn('Unsupported event type');
                    break;
            }
        }
    }, {
        key: "removeAllEventListener",
        value: function removeAllEventListener() {}
    }, {
        key: "dispatchEvent",
        value: function dispatchEvent(name, type) {
            var data = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
            var eventScope = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : EventScope.CurrentBundle;

            //全局广播的事件,只能用于Web事件
            if (eventScope === EventScope.GlobalBundle && type === EventType.WebEvent) {
                eventBusManager.broadcast(name, data);
                return -1;
            }
            //处理其他情况
            switch (type) {
                case EventType.WebEvent:
                    this._webEventBus.dispatch(name, data);
                    return 0;
                case EventType.NativeEvent:
                    return this._nativeEventBus.callNative(MidwayConfig.NativeBridgeClass, name, data);
                case EventType.PPTEvent:
                    return this._nativeEventBus.callNative(MidwayConfig.NativeBridgeClass, 'sendEvent', {
                        eventName: name,
                        eventData: data
                    });
                default:
                    console.warn('Unsupported event type');
                    break;
            }
        }
    }, {
        key: "WebEventBus",
        get: function get$$1() {
            return this._webEventBus;
        }
    }]);
    return EventBus;
}();

var EventBusManager = function (_BasicManager) {
    inherits(EventBusManager, _BasicManager);

    function EventBusManager() {
        var _ret;

        classCallCheck(this, EventBusManager);

        if (!EventBusManager.instance) {
            var _this = possibleConstructorReturn(this, (EventBusManager.__proto__ || Object.getPrototypeOf(EventBusManager)).call(this));

            EventBusManager.instance = _this;
        }

        return _ret = EventBusManager.instance, possibleConstructorReturn(_this, _ret);
    }

    createClass(EventBusManager, [{
        key: "create",
        value: function create(ctx) {
            var webBus = new WebEventBus();
            var nativeBus = window.top === undefined ? window.Bridge : window.top.Bridge;
            var eventBus = new EventBus(webBus, nativeBus);
            this.add(ctx.Key, eventBus);
            return eventBus;
        }
    }, {
        key: "broadcast",
        value: function broadcast(name, data) {
            this.each(function (key, item) {
                item.WebEventBus.dispatch(name, data);
            });
        }
    }]);
    return EventBusManager;
}(BasicManager);

var eventBusManager = new EventBusManager();

var ModuleLibLoader = function () {
    function ModuleLibLoader() {
        classCallCheck(this, ModuleLibLoader);
    }

    createClass(ModuleLibLoader, [{
        key: "load",
        value: function load(bundle) {
            var def = jQuery.Deferred();
            if (bundle.prototype.__dependLibs && Array.prototype.isArray(bundle.prototype.__dependLibs)) {
                var dependLibs = bundle.prototype.__dependLibs;
                var scripts = [];
                //检查需要加载的第三方库
                dependLibs.forEach(function (item) {
                    if (scriptLibraryManager.exists(item)) {
                        var config = scriptLibraryManager.get(item);
                        //如果未载过
                        if (config.loaded === false) {
                            scripts.push(config);
                        }
                    }
                });
                if (scripts.length === 0) {
                    //没有需要额外加载的类库
                    def.resolve();
                } else {
                    var loadLibs = [];
                    scripts.forEach(function (lib) {
                        JsLibLoader.findDependScript(lib, loadLibs);
                    });
                    var loader = JsLibLoader.getInstance().create();
                    loader.load(loadLibs).done(function () {
                        //类库加载完成
                        loadLibs.forEach(function (item) {
                            item.loaded = true;
                        });
                        def.resolve();
                    }).fail(function () {
                        console.error('Load bundle depend library error');
                        def.reject();
                    });
                }
            } else {
                def.resolve();
            }
            return def.promise();
        }
    }]);
    return ModuleLibLoader;
}();

var ModuleLoader = function () {
    var instance = void 0;
    return {
        name: "ModuleLoader",
        getInstance: function getInstance() {
            if (instance === undefined) {
                instance = new ModuleLibLoader();
            }
            return instance;
        }
    };
}();

var moduleDOMTemplate = "<div class='module_${module}' id='${id}'></div>";
var cssReg = /url\s*\(\s*(['"]?)(resources[\\/].*?)\1\s*\)/ig;
var cssUrlTemplate = 'url("${base}/${code}/${name}")';

var ModuleRender = {
    render: function render(key, code, style, view, container, attrs) {
        //渲染Module的样式部分
        if (style) {
            var exists = ScriptRender.checkStyle(function (item) {
                if (item.attributes['moduleCode']) {
                    return item.attributes['moduleCode'].value === code;
                }
                return false;
            });
            //如果不存在样式,则添加进去
            if (!exists) {
                var styleStr = style.toString();
                var css = styleStr.replace(cssReg, function ($0, $1, $2) {
                    return stringUtils.applyTemplate(cssUrlTemplate, { base: MidwayConfig.BundlePath, code: code, name: $2 });
                });
                ScriptRender.addEmbedStyle(css, { moduleCode: code });
            }
        }
        if (view) {
            //渲染Module的Template
            var element = jQuery.parseHTML(stringUtils.applyTemplate(moduleDOMTemplate, {
                "module": code,
                "id": key
            }))[0];
            if (attrs) {
                for (var _key in attrs) {
                    if (_key === 'style') {
                        for (var styleKey in attrs[_key]) {
                            element.style[styleKey] = attrs[_key][styleKey];
                        }
                    } else {
                        element.setAttribute(_key, attrs[_key]);
                    }
                }
            }
            element.appendChild(view);
            container.appendChild(element);
        }
    }
};

var requestParams = {
    params: {},
    get: function get() {
        return requestParams.params;
    }
};

var search = location.search;
search = search.substr(1, search.length);
var params = search.split('&');
params.forEach(function (name) {
    var p = name.split("=");
    var key = p[0];
    if (key) {
        requestParams.params[key] = decodeURIComponent(p[1]);
    }
});

var controlMethod = {
    BEFORE_RUN: 'processBeforeRun',
    AFTER_RUN: 'processAfterRun'
};
var lifecycleMethod = {
    render: ["beforeRender"],
    run: ["beforeRun", "run", "afterRun"],
    update: ["update"],
    show: ["pageShow"],
    destroy: ["destroy"]
};

var ModuleProcessor = function () {
    function ModuleProcessor(options) {
        classCallCheck(this, ModuleProcessor);

        this._instance = options.instance;
        this._context = options.context;

        this._key = stringUtils.randomWord(false, 8);
        this._code = options.code;
        this._style = options.style;
        this._container = options.container;
        this._model = options.model;
        this._view = options.template;

        this._hasRunning = {};
        this._isController = isController(this._instance);
    }

    createClass(ModuleProcessor, [{
        key: "render",
        value: function render(attributes) {
            ModuleRender.render(this._key, this._code, this._style, this._view, this._container, attributes);
        }

        /**
         * @summary 执行生命周期前方法, 方法皆为同步过程
         */

    }, {
        key: "runInit",
        value: function runInit() {
            supportFunction.execute(this._instance, {
                'setPlayerController': this._context,
                'setUrlParams': requestParams.get(),
                'setBasePath': MidwayConfig.BasePath
            });
        }

        /**
         * 执行生命周期方法
         * @param lifecycle 生命周期
         * @extend 扩展方法参数
         * @
         * @returns {*}
         */

    }, {
        key: "runLifecycle",
        value: function runLifecycle(lifecycle) {
            var _this = this;

            var taskList = [];
            lifecycle.forEach(function (name) {
                taskList.push({
                    fn: _this._instance[name],
                    args: [_this._view, _this._model],
                    scope: _this._instance,
                    name: ""
                });
            });
            return supportFunction.runSequence(taskList, "run bundle lifecycle");
        }
    }, {
        key: "ModuleInstance",
        get: function get$$1() {
            return this._instance;
        }
    }, {
        key: "ModuleCode",
        get: function get$$1() {
            return this._code;
        }
    }, {
        key: "ProcessorKey",
        get: function get$$1() {
            return this._key;
        }
    }, {
        key: "RunningModules",
        get: function get$$1() {
            return this._hasRunning;
        }
    }, {
        key: "IsController",
        get: function get$$1() {
            return this._isController;
        }
    }, {
        key: "Model",
        set: function set$$1(model) {
            if (model) {
                this._model = model;
            }
        }
    }]);
    return ModuleProcessor;
}();

function isController(instance) {
    return !!(instance[controlMethod.BEFORE_RUN] && instance[controlMethod.AFTER_RUN]);
}

/**
 * 支持组件方法
 * @param name 方法名称
 * @param args 方法参数
 */
var Workflow = function () {
    function Workflow() {
        classCallCheck(this, Workflow);

        this._playerflows = {};
    }

    createClass(Workflow, [{
        key: "start",
        value: function start(flowData, successCallback, failCallback) {}
    }, {
        key: "PlayerFlows",
        get: function get$$1() {
            return this._playerflows;
        }
    }], [{
        key: "registerFlow",
        value: function registerFlow(options) {
            if (this instanceof Bundle) {
                assert(options.key === undefined, 'work flow key can not undefined');
                var playerFlows = WorkFlowInstance.getInstance().PlayerFlows;
                if (!supportFunction.hasProp(playerFlows, this.Key)) {
                    playerFlows[this.Key] = {};
                }
                playerFlows[this.Key][options.key] = options;
            } else {
                console.error('Please use Bundle objects for workflow calls');
            }
        }
    }, {
        key: "startFlow",
        value: function startFlow(key, data, success, fail) {
            if (this instanceof Bundle) {
                var flows = WorkFlowInstance.getInstance().PlayerFlows[this.Key];
                if (supportFunction.hasProp(flows, 'key')) {} else {
                    console.error('Can not find the specified workflow configuration, key=' + key);
                }
            } else {
                console.error('Please use Bundle objects for workflow calls');
            }
        }
    }]);
    return Workflow;
}();

var WorkFlowInstance = function () {
    var instance = void 0;
    return {
        name: "WorkFlowInstance",
        getInstance: function getInstance() {
            if (instance === undefined) {
                instance = new Workflow();
            }
            return instance;
        }
    };
}();

/**
 * @private
 * XML节点基类
 */
var XMLNode =

//节点类型，1：XML，2：XMLAttribute，3：XMLText
function XMLNode(nodeType, parent) {
    classCallCheck(this, XMLNode);

    this.nodeType = nodeType;
    this.parent = parent;
};

/**
 * @private
 * XML节点对象
 */
var XML = function (_XMLNode) {
    inherits(XML, _XMLNode);

    function XML(localName, parent, prefix, namespace, name) {
        classCallCheck(this, XML);

        var _this = possibleConstructorReturn(this, (XML.__proto__ || Object.getPrototypeOf(XML)).call(this, 1, parent));

        _this.localName = localName;
        _this.prefix = prefix;
        _this.namespace = namespace;
        _this.name = name;
        _this.attributes = {};
        _this.children = [];
        return _this;
    }

    return XML;
}(XMLNode);

/**
 * @private
 * XML文本节点
 */
var XMLText = function (_XMLNode2) {
    inherits(XMLText, _XMLNode2);

    function XMLText(text, parent) {
        classCallCheck(this, XMLText);

        var _this2 = possibleConstructorReturn(this, (XMLText.__proto__ || Object.getPrototypeOf(XMLText)).call(this, 3, parent));

        _this2.text = text;
        return _this2;
    }

    return XMLText;
}(XMLNode);

var parser = new DOMParser();



function xmlToJsonByAttr(obj, node, attrs, eachFn) {
    if (!jQuery.isPlainObject(obj)) {
        eachFn = attrs;
        attrs = node;
        node = obj;
        obj = {};
    }
    if (node) {
        attrs.forEach(function (attr) {
            var mapKey = void 0;
            if (typeof attr === "string") {
                mapKey = attr;
            } else {
                for (var key in attr) {
                    mapKey = key;
                    attr = attr[key];
                }
            }
            var value = (jQuery.isFunction(attr) ? attr(node.getAttribute(mapKey) || "") : node.getAttribute(attr)) || "";
            if (jQuery.isFunction(eachFn)) {
                value = eachFn(value, mapKey);
            }
            obj[mapKey] = value;
        });
    }
    return obj;
}

var BaseModel = function () {
    function BaseModel() {
        classCallCheck(this, BaseModel);

        this.attributeValues = {};
        this.attributes = [];
    }

    createClass(BaseModel, [{
        key: "setAttribute",
        value: function setAttribute(name, value) {
            if (name in this.attributeValues) {
                this.attributeValues[name] = value;
            }
        }
    }, {
        key: "setAttributes",
        value: function setAttributes(attrs) {
            for (var key in attrs) {
                this.setAttribute(key, attrs[key]);
            }
        }
    }, {
        key: "getAttribute",
        value: function getAttribute(name) {
            return this.attributeValues[name];
        }
    }, {
        key: "removeAttribute",
        value: function removeAttribute(name) {
            var value = this.getAttribute(name);
            delete this.attributeValues[name];
            return value;
        }
    }, {
        key: "AttributeValues",
        get: function get$$1() {
            return this.attributeValues;
        }
    }, {
        key: "Attributes",
        get: function get$$1() {
            return this.attributes;
        }
    }]);
    return BaseModel;
}();

var MainModel = function (_BaseModel) {
    inherits(MainModel, _BaseModel);

    function MainModel() {
        classCallCheck(this, MainModel);

        var _this = possibleConstructorReturn(this, (MainModel.__proto__ || Object.getPrototypeOf(MainModel)).call(this));

        _this.attributes = ["pages", "css", "style", "commons", "model"];
        _this.attributes.forEach(function (item) {
            _this.attributeValues[item] = [];
        });
        return _this;
    }

    createClass(MainModel, [{
        key: "addPage",
        value: function addPage(page) {
            this.getAttribute("pages").push(page);
        }
    }, {
        key: "getPages",
        value: function getPages() {
            return this.getAttribute('pages');
        }
    }, {
        key: "addModule",
        value: function addModule(model) {
            this.getAttribute("model").push(model);
        }
    }]);
    return MainModel;
}(BaseModel);

var ModuleModel = function (_BaseModel) {
    inherits(ModuleModel, _BaseModel);

    function ModuleModel() {
        classCallCheck(this, ModuleModel);

        var _this = possibleConstructorReturn(this, (ModuleModel.__proto__ || Object.getPrototypeOf(ModuleModel)).call(this));

        _this.attributes = ['id', 'presenterId', 'layout', 'css', 'style', 'z-index', 'lazy-init', 'properties', 'events'];
        _this.attributes.forEach(function (item) {
            _this.attributeValues[item] = [];
        });
        return _this;
    }

    createClass(ModuleModel, [{
        key: 'addProperty',
        value: function addProperty(property) {
            this.getAttribute('properties').push(property);
        }
    }]);
    return ModuleModel;
}(BaseModel);

var modelFile = new RegExp(/(http|https|file):\/\/(\/)?([^\:|\/]+)(\:\d*)?(.*\/)([^#|\?|\n]+)?(#.*)?(\?.*)?/i);

var ModelLoader = function () {
    function ModelLoader() {
        classCallCheck(this, ModelLoader);
    }

    createClass(ModelLoader, null, [{
        key: "loadModel",
        value: function loadModel(launcher, url) {
            var mainUrl = testFile(url);
            if (mainUrl.url === undefined) {
                throw Error('can not found main.xml');
            }
            if (mainUrl.absolute === false) {
                mainUrl.url = stringUtils.urlJoin(MidWayConfig.BasePath, url);
            }
            return jQuery.ajax({
                url: mainUrl.url,
                method: 'GET',
                dataType: "text",
                cache: false,
                async: false
            }).then(function (data) {
                var result = pageXMLParse(data);
                result.baseUrl = mainUrl.baseUrl;
                questionXMLPage(launcher, result);
                var model = result.getAttribute('model');
                var questionModel = {};
                if (model.length > 0) {
                    var properties = model[0].getAttribute("properties");
                    properties.forEach(function (property) {
                        if (property.type === 'json') {
                            questionModel[property.name] = JSON.parse(property.value);
                        } else if (property.type === 'jsonFile') {
                            var _url = stringUtils.urlJoin(mainUrl.baseUrl, 'pages', property.value);
                            jQuery.ajax({
                                url: _url,
                                dataType: "json",
                                async: false
                            }).done(function (data) {
                                questionModel[property.name] = data;
                            });
                        } else {
                            questionModel[property.name] = property.value;
                        }
                    });
                }
                return questionModel;
            });
        }
    }]);
    return ModelLoader;
}();

function pageXMLParse(text) {
    var $dom = jQuery(jQuery.parseXML(text));
    var model = new MainModel(),
        commonPages = model.getAttribute('commons'),
        index = 0,
        parentTagName = void 0;

    $dom.find('page').each(function (i, page) {
        var pageInfo = xmlToJsonByAttr(page, ['id', 'name', 'href', 'preview']);
        pageInfo.id = pageInfo.id || 'page_' + index;
        parentTagName = page.parentNode.tagName.toLowerCase();
        if (parentTagName === 'folder') {
            if (pageInfo.name) {
                commonPages.addItem(pageInfo.name, pageInfo);
            }
        } else {
            if (parentTagName === 'coursewareobject') {
                var rootPath = page.parentNode.getAttribute("rootPath");
                pageInfo.href = rootPath + pageInfo.href;
            }
            model.addPage(pageInfo);
        }
        index++;
    });
    return model;
}

function questionXMLPage(launcher, page) {
    var pages = page.getPages();
    if (pages && pages.length > 0) {
        var questionUrl = stringUtils.urlJoin(page.baseUrl, pages[0].href);
        jQuery.ajax({
            url: questionUrl,
            method: "GET",
            async: false
        }).done(function (data) {
            jQuery(data).find('page').children('modules').each(function (index, element) {
                questionXMLParse(launcher, page, element);
            });
        });
    }
}

function questionXMLParse(launcher, parent, modules) {
    var index = 0;
    jQuery(modules).children('module, addonModule').each(function (i, module) {
        var model = new ModuleModel();
        var modelConfig = xmlToJsonByAttr(module, ['addonId', 'moduleId', 'presenterId', 'id', 'isVisible', 'isLocked', 'style', {
            'lazy-init': function lazyInit(value) {
                return value.toLowerCase() === 'true';
            }
        }]);
        if (modelConfig.addonId === launcher || modelConfig.moduleId === launcher) {
            if (!modelConfig.presenterId && modelConfig.addonId) {
                modelConfig.presenterId = modelConfig.addonId;
            }
            modelConfig.id = modelConfig.id || 'module_' + index;
            $(module).children().each(function (i, element) {
                var fn = parseModule[element.tagName];
                if (jQuery.isFunction(fn)) {
                    fn(model, element);
                }
            });
            parent.addModule(model);
            index++;
        }
    });
}

function testFile(url) {
    if (url.indexOf('main.xml') === -1) {
        console.error("can not found main.xml!");
        return { absolute: false, url: undefined };
    }
    var basePath = url.replace('main.xml', '');
    var result = url.match(modelFile);
    return { absolute: result !== null, baseUrl: basePath, url: url };
}

var parseModule = {
    'style': function style(module, element) {
        module.setAttribute('css', $(element).attr('href'));
        var style = $(element).text();
        if (style) {
            module.setAttribute('style', style);
        }
    },
    'events': function events(module, element) {
        $(element).children('event').each(function (i, event) {
            var $event = $(event);
            var eventName = $event.attr('name');
            if (eventName) {
                var handlerList = [];
                $event.children('handler').each(function (j, handler) {
                    handlerList.push(utilsXML.toJsonByAttr(handler, [{ 'id': 'targetId' }, { 'name': 'handlerName' }]));
                });
                if (handlerList.length) {
                    module.addEvent(eventName, handlerList);
                }
            }
        });
    },
    'properties': function properties(module, element) {
        buildProperty(element, function (oProp) {
            module.addProperty(oProp);
        });
    }
};

function buildProperty(element, fn) {
    jQuery(element).children('property').each(function (i, prop) {
        var oProp = void 0;
        if (prop.getAttribute('type') === 'list') {
            oProp = utilsXML.toJsonByAttr(prop, ['name', 'type']);
            oProp.value = [];
            jQuery(prop).find('items>item').each(function (i, item) {
                var itemProps = [];
                buildProperty(item, function (oProp) {
                    itemProps.push(oProp);
                });
                oProp.value.push(itemProps);
            });
        } else {
            oProp = xmlToJsonByAttr(prop, ['name', 'type', 'value']);
            var sText = jQuery.trim($(prop).text());
            if (sText) {
                oProp.text = sText;
            }
        }
        fn(oProp);
    });
}

var WekMapPolyFill = function () {
    function WekMapPolyFill() {
        classCallCheck(this, WekMapPolyFill);

        if (this === void 0) {
            throw new TypeError("Constructor WeakMap requires 'new'");
        }
        this._id = genId('_WeakMap');
        this._polyfill = true;
        if (arguments.length > 0) {
            throw new TypeError('WeakMap iterable is not supported');
        }
    }

    createClass(WekMapPolyFill, [{
        key: 'delete',
        value: function _delete(key) {
            checkInstance(this, 'delete');

            if (!isObject(key)) {
                return false;
            }

            var entry = key[this._id];
            if (entry && entry[0] === key) {
                delete key[this._id];
                return true;
            }

            return false;
        }
    }, {
        key: 'get',
        value: function get$$1(key) {
            checkInstance(this, 'get');

            if (!isObject(key)) {
                return void 0;
            }

            var entry = key[this._id];
            if (entry && entry[0] === key) {
                return entry[1];
            }

            return void 0;
        }
    }, {
        key: 'has',
        value: function has(key) {
            checkInstance(this, 'has');

            if (!isObject(key)) {
                return false;
            }

            var entry = key[this._id];
            return !!(entry && entry[0] === key);
        }
    }, {
        key: 'set',
        value: function set$$1(key, value) {
            checkInstance(this, 'set');

            if (!isObject(key)) {
                throw new TypeError('Invalid value used as weak map key');
            }

            var entry = key[this._id];
            if (entry && entry[0] === key) {
                entry[1] = value;
                return this;
            }

            defineProperty$1(key, this._id, [key, value]);
            return this;
        }
    }]);
    return WekMapPolyFill;
}();

function defineProperty$1(object, name, value) {
    if (Object.defineProperty) {
        Object.defineProperty(object, name, {
            configurable: true,
            writable: true,
            value: value
        });
    } else {
        object[name] = value;
    }
}

function checkInstance(x, methodName) {
    if (!isObject(x) || !Object.prototype.hasOwnProperty.call(x, '_id')) {
        throw new TypeError(methodName + ' method called on incompatible receiver ' + (typeof x === 'undefined' ? 'undefined' : _typeof(x)));
    }
}

function isObject(x) {
    return Object(x) === x;
}

function genId(prefix) {
    return prefix + '_' + rand() + '.' + rand();
}

function rand() {
    return Math.random().toString().substring(2);
}

//poly fill
if (!window.WeakMap) {
    window.WeakMap = WekMapPolyFill;
}

var _bundleProcessor = new WeakMap();
var _bundleRunning = new WeakMap();
var _bundleEventBus = new WeakMap();

var Bundle = function () {
    function Bundle(options) {
        var _this = this;

        classCallCheck(this, Bundle);

        if (!supportFunction.hasProp(Midway, 'hasReady')) {
            throw Error('Component is not initialized or initialization is not completed!');
        }

        assert(options === void 0, "init options can't null");
        //assert(options.el === undefined, "init options must contain 'el' property");
        assert(options.launcher === undefined, "init options must contain 'launcher' property");
        //如果没有传递el, 则默认渲染到body上
        var container = options.el ? jQuery.find(options.el) : [document.body];
        assert(container.length === 0, "can not find the specified container element");

        this._containElement = container[0];
        this._launcher = options.launcher;
        this._model = {};

        if (options.model !== undefined) {
            this._model = options.model;
        } else if (options.modelUrl !== undefined) {
            ModelLoader.loadModel(this._launcher, options.modelUrl).done(function (data) {
                _this._model = data;
            });
        }
        Object.defineProperty(this, '__key', { value: stringUtils.randomWord(false, 8) });
        _bundleProcessor.set(this, []);
        _bundleRunning.set(this, false);
        _bundleEventBus.set(this, undefined);
        //设置容器属性
        this._containElement.setAttribute("bundle", this.Key);
    }

    createClass(Bundle, [{
        key: "start",


        /**
         * 启动模块
         */
        value: function start(fn) {
            var _this2 = this;

            if (_bundleRunning.get(this) === true) {
                console.warn('This bundle is running');
                return;
            }
            _bundleRunning.set(this, true);
            loadModule(this._launcher).done(function (obj) {
                if (obj.module) {
                    //加载Bundle所需的样式和外部脚本库
                    ModuleLoader.getInstance().load(obj.module).done(function () {
                        //创建事件总线对象
                        var eb = eventBusManager.create(_this2);
                        _bundleEventBus.set(_this2, eb);
                        //创建启动模块
                        createProcessor.call(_this2, obj.module, {
                            code: obj.module.prototype.__code,
                            model: _this2.Model,
                            rendTo: _this2._containElement,
                            attributes: { style: { width: '100%', height: '100%' } }
                        });
                        if (fn) {
                            fn();
                        }
                    });
                }
            });
        }

        /**
         * 重置模块的模型, 本方法会通过执行Bundle中第一个Processor; 即Launcher中的update方法来更新模块的数据结构
         * @param model 待更新的模块模型
         */

    }, {
        key: "update",
        value: function update(model) {
            var _this3 = this;

            var running = _bundleRunning.get(this);
            if (running === undefined) {
                console.warn('Bundle has been destroyed and can not execute the release method');
                return;
            }
            if (running === false) {
                console.warn('This bundle not running');
                return;
            }

            var launcher = this.Processors[0];
            if (launcher) {
                if (typeof model === 'string') {
                    ModelLoader.loadModel(this._launcher, model).done(function (data) {
                        launcher.Model = data;
                    });
                } else if (jQuery.isPlainObject(model)) {
                    launcher.Model = data;
                } else {
                    console.error('Invalid input parameter');
                    return;
                }
                launcher.runLifecycle(lifecycleMethod.update).done(function (data) {
                    if (data !== undefined) {
                        var dispatchModel = data.dispatch || false;
                        if (dispatchModel === true && data.adaptedModel !== undefined) {
                            for (var index = 1, len = _this3.Processors.length; index < len; index++) {
                                var processor = _this3.Processors[index];
                                if (data.adaptedModel[processor.ModuleCode] !== undefined) {
                                    processor.Model = data.adaptedModel[processor.ModuleCode];
                                    processor.runLifecycle(lifecycleMethod.update);
                                }
                            }
                        }
                    }
                });
            }
        }

        /**
         * 释放模块
         */

    }, {
        key: "release",
        value: function release() {
            var running = _bundleRunning.get(this);
            if (running === undefined) {
                console.warn('Bundle has been destroyed and can not execute the release method');
                return;
            }
            if (running === false) {
                console.warn('This bundle not running');
                return;
            }
            //释放事件总线
            this.EventBus.removeAllEventListener();
            eventBusManager.remove(this.Key);
            _bundleEventBus.delete(this);
            //释放处理器对象
            var processors = _bundleProcessor.get(this);
            var _iteratorNormalCompletion = true;
            var _didIteratorError = false;
            var _iteratorError = undefined;

            try {
                for (var _iterator = processors[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
                    var item = _step.value;

                    item.runLifecycle(lifecycleMethod.destroy);
                }
            } catch (err) {
                _didIteratorError = true;
                _iteratorError = err;
            } finally {
                try {
                    if (!_iteratorNormalCompletion && _iterator.return) {
                        _iterator.return();
                    }
                } finally {
                    if (_didIteratorError) {
                        throw _iteratorError;
                    }
                }
            }

            _bundleProcessor.set(this, []);
            //释放Processor
            _bundleProcessor.delete(this);
            //删除Bundle的DOM
            if (this._containElement.firstChild) {
                this._containElement.firstChild.remove();
            }
            //删除Bundle运行标志
            _bundleRunning.delete(this);
        }

        /**
         * 提供外部能够直接调用Bundle中Processor方法的统一接口
         * @param method 方法名称
         * @param args 方法参数
         * @param options 运行配置包括
         * that: 指定方法运行的作用对象, 不指定时使用Processor对象
         * key: 指定调用Processor的Key, 如果没有特殊指定则使用第一个Processor, 即启动Processor
         */

    }, {
        key: "invoke",
        value: function invoke(method, args) {
            var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};

            var processor = undefined,
                scope = undefined;
            if (!options.key) {
                processor = this.Processors[0];
            } else {
                var _iteratorNormalCompletion2 = true;
                var _didIteratorError2 = false;
                var _iteratorError2 = undefined;

                try {
                    for (var _iterator2 = this.Processors[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
                        var item = _step2.value;

                        if (item.ModuleCode === options.key) {
                            processor = item;
                            break;
                        }
                    }
                } catch (err) {
                    _didIteratorError2 = true;
                    _iteratorError2 = err;
                } finally {
                    try {
                        if (!_iteratorNormalCompletion2 && _iterator2.return) {
                            _iterator2.return();
                        }
                    } finally {
                        if (_didIteratorError2) {
                            throw _iteratorError2;
                        }
                    }
                }
            }
            if (!processor) {
                throw Error('Can not find the specified processor');
            }
            if (processor[method] === undefined) {
                throw Error('The specified method does not exist in the processor');
            }
            scope = options.that || processor;

            try {
                var def = jQuery.Deferred().resolve();
                return def.then(function () {
                    return processor[method].call(scope, args);
                }).done(function () {
                    console.info('invoke method over');
                });
            } catch (e) {
                throw Error('Method execution error', e);
            }
        }
    }, {
        key: "Key",
        get: function get$$1() {
            return supportFunction.getOwn(this, '__key');
        }
    }, {
        key: "Model",
        get: function get$$1() {
            return this._model;
        }
    }, {
        key: "Processors",
        get: function get$$1() {
            return _bundleProcessor.get(this);
        }
    }, {
        key: "EventBus",
        get: function get$$1() {
            return _bundleEventBus.get(this);
        }
    }]);
    return Bundle;
}();

Object.defineProperty(Bundle.prototype, 'require', {
    value: function value(options) {
        var _this4 = this;

        assert(typeof options.code !== 'string', 'The requested module code can not be empty');
        var def = jQuery.Deferred();
        loadModule(options.code).done(function (obj) {
            assert(obj.module === undefined, "Unable to load the specified module:" + options.code);
            ModuleLoader.getInstance().load(obj.module).done(function () {
                var processor = createProcessor.call(_this4, obj.module, options);
                def.resolve(processor.ModuleInstance);
            });
        });
        return def.promise();
    }
});
Object.defineProperty(Bundle.prototype, 'getEventBus', {
    value: function value() {
        return this.EventBus;
    }
});
Object.defineProperty(Bundle.prototype, 'registerFlow', {
    value: function value() {
        if (arguments.length < 2) {
            console.warn("The number of parameters is incorrect");
            return;
        }
        var options = jQuery.extend(arguments[1], { key: arguments[0] });
        Workflow.registerFlow.call(this, options);
    }
});
Object.defineProperty(Bundle.prototype, 'startFlow', {
    value: function value() {
        Workflow.startFlow.apply(this, arguments);
    }
});

var bundlePromise = {};

function createBundlePromise(code) {
    if (!supportFunction.hasProp(bundlePromise, code)) {
        bundlePromise[code] = jQuery.Deferred();
    }
    return supportFunction.getOwn(bundlePromise, code);
}

function getBundlePromise(code) {
    if (!supportFunction.hasProp(code)) {
        return createBundlePromise(code);
    }
    return supportFunction.getOwn(bundlePromise, code);
}

function createProcessor(clazz, options) {
    var _this5 = this;

    var instance = new clazz();
    var _options$code = options.code,
        code = _options$code === undefined ? options.code : _options$code,
        _options$model = options.model,
        model = _options$model === undefined ? options.model || {} : _options$model,
        _options$attributes = options.attributes,
        attributes = _options$attributes === undefined ? options.attributes || undefined : _options$attributes;

    var rendTo = options.rendTo === undefined || options.rendTo === null ? this._containElement : options.rendTo;
    var template = undefined;
    if (clazz.prototype.__template !== undefined) {
        template = clazz.prototype.__template.cloneNode(true);
    }
    var processor = new ModuleProcessor({
        code: code,
        template: template,
        style: clazz.prototype.__style,
        model: model,
        instance: instance,
        container: rendTo,
        context: this
    });
    this.Processors.push(processor);
    //执行模块生命周期流程
    processor.runInit();
    processor.runLifecycle(lifecycleMethod.render);
    //配置附加属性
    processor.render(attributes);
    runControl.call(this, controlMethod.BEFORE_RUN, processor);
    processor.runLifecycle(lifecycleMethod.run).done(function () {
        runControl.call(_this5, controlMethod.AFTER_RUN, processor);
        processor.runLifecycle(lifecycleMethod.show);
    });
    return processor;
}

function runControl(name, currentProcess) {
    var processors = this.Processors;
    processors.forEach(function (processor) {
        var currentKey = currentProcess.ProcessorKey,
            tempKey = processor.ProcessorKey;
        if (tempKey !== currentKey && processor.IsController) {
            if (!supportFunction.hasProp(processor.RunningModules, name)) {
                processor.RunningModules[name] = [];
            }
            if (processor.RunningModules[name].findIndex(function (item) {
                return item === currentKey;
            }) === -1) {
                processor.RunningModules[name].push(currentKey);
                supportFunction.execute(processor.ModuleInstance, name, currentProcess.ModuleInstance);
            }
        }
    });
    if (currentProcess.IsController) {
        processors.forEach(function (processor) {
            var currentKey = currentProcess.ProcessorKey,
                tempKey = processor.ProcessorKey;
            if (tempKey !== currentKey) {
                if (!supportFunction.hasProp(currentProcess.RunningModules, name)) {
                    currentProcess.RunningModules[name] = [];
                }
                if (currentProcess.RunningModules[name].findIndex(function (item) {
                    return item === tempKey;
                }) === -1) {
                    currentProcess.RunningModules[name].push(currentKey);
                    supportFunction.execute(currentProcess.ModuleInstance, name, processor.ModuleInstance);
                }
            }
        });
    }
}

function loadModule(code) {
    var bundleConfig = moduleManager.ModuleConfig;

    if (!supportFunction.hasProp(bundleConfig, code)) {
        throw Error('Can not find configuration information for specified Bundle!');
    }
    var config = bundleConfig[code];
    var promise = getBundlePromise(code);
    if (config.loaded === true) {
        return promise.promise();
    }
    if (moduleManager.exists(code)) {
        //如果已经加载过
        promise.resolve({ module: moduleManager.get(code) });
    } else {
        //如果还没有加载过
        config.loaded = true;
        //加载指定URL的bundle
        ScriptRender.addJavascript(config.href).done(function () {
            promise.resolve({ module: moduleManager.get(code) });
        }).fail(function () {
            promise.reject();
            throw Error('Load Bundle error');
        });
    }
    return promise.promise();
}

var _functionMap = new WeakMap();
var _listenerMap = new WeakMap();

var NativeEventBridge = function () {
    function NativeEventBridge(bridge) {
        classCallCheck(this, NativeEventBridge);

        this._bridgeInterface = bridge;
        for (var key in defaultBridge) {
            if (this._bridgeInterface[key] === undefined) {
                this._bridgeInterface[key] = defaultBridge[key];
            }
        }
        _functionMap.set(this, {});
        _listenerMap.set(this, {});
    }

    createClass(NativeEventBridge, [{
        key: 'callNative',
        value: function callNative() {
            if (arguments.length < 2) {
                return;
            }
            var className = arguments[0],
                methodName = arguments[1],
                argLen = arguments.length - 2;
            if (argLen === 0) {
                return this._bridgeInterface.invokeMethod(className, methodName);
            } else if (argLen === 1) {
                this._bridgeInterface.printLog('==IcPlayer Player callNative: ' + className + "." + methodName + " arg=" + JSON.stringify(arguments[2]));
                var result = this._bridgeInterface.invokeMethod(className, methodName, JSON.stringify(arguments[2]));
                try {
                    return JSON.parse(result);
                } catch (e) {
                    return {};
                }
            }
        }
    }, {
        key: 'callNativeAsync',
        value: function callNativeAsync() {
            if (arguments.length < 3) {
                return;
            }
            var className = arguments[0],
                methodName = arguments[1];
            var fn = arguments[2],
                callback = void 0;
            if (typeof fn === 'function') {
                callback = this._addCallbackFunc(fn);
                return this._bridgeInterface.invokeMethodAsync(className, methodName, callback);
            } else {
                var param = fn;
                fn = arguments[3];
                if (typeof fn === 'function') {
                    callback = this._addCallbackFunc(fn);
                    return this._bridgeInterface.invokeMethodAsync(className, methodName, callback, JSON.stringify(param));
                }
            }
        }
    }, {
        key: 'registerListener',
        value: function registerListener(name, fn, scope) {
            var key = this._addListenerFunc(name, fn, scope);
            var callBack = "Bridge.listenerInvokeFromNative('" + key + "',==param==)";
            this._bridgeInterface.registerListener(name, callBack);
        }
    }, {
        key: 'listenerInvokeFromNative',
        value: function listenerInvokeFromNative(callId, param) {
            var listener = this.ListenerMap[callId];
            if (listener === undefined || listener.callback === undefined) {
                return;
            }
            listener.callback.call(listener.scope, param);
        }
    }, {
        key: 'callBackFromNative',
        value: function callBackFromNative(callId, param) {
            var func = this.FunctionMap[callId];
            if (func === undefined) {
                this.FunctionMap[callId] = undefined;
                return;
            }
            func(param);
            this.FunctionMap[callId] = null;
        }
    }, {
        key: 'unRegisterListener',
        value: function unRegisterListener(name, key) {
            var callBack = "Bridge.listenerInvokeFromNative('" + key + "',==param==)";
            this._removeListenerFunc(key);
            this._bridgeInterface.unRegisterListener(name, callBack);
        }
    }, {
        key: '_addListenerFunc',
        value: function _addListenerFunc(event, fn, scope) {
            var key = this.randomKey(10);
            this.ListenerMap[key] = {
                eventName: event,
                callback: fn,
                scope: scope || window
            };
            return key;
        }
    }, {
        key: '_removeListenerFunc',
        value: function _removeListenerFunc(key) {
            delete this.ListenerMap[key];
        }
    }, {
        key: '_addCallbackFunc',
        value: function _addCallbackFunc(fn) {
            var key = this.randomKey(10);
            this.FunctionMap[key] = fn;
            return "Bridge.callBackFromNative('" + key + "',==param==)";
        }
    }, {
        key: 'randomKey',
        value: function randomKey(len) {
            var x = "0123456789qwertyuioplkjhgfdsazxcvbnm",
                timestamp = new Date().getTime();
            var tmp = "";
            for (var i = 0; i < len; i++) {
                tmp += x.charAt(Math.ceil(Math.random() * 100000000) % x.length);
            }
            return timestamp + tmp;
        }
    }, {
        key: 'FunctionMap',
        get: function get$$1() {
            return _functionMap.get(this);
        }
    }, {
        key: 'ListenerMap',
        get: function get$$1() {
            return _listenerMap.get(this);
        }
    }]);
    return NativeEventBridge;
}();

var defaultBridge = {
    'invokeMethod': function invokeMethod() {
        console.warn('this message from default bridge! there is noting happening here!!');
        return {};
    },
    'printLog': function printLog() {
        console.warn('this message from default bridge! there is noting happening here!!');
    },
    'invokeMethodAsync': function invokeMethodAsync() {
        console.warn('this message from default bridge! there is noting happening here!!');
    },
    'registerListener': function registerListener() {
        console.warn('this message from default bridge! there is noting happening here!!');
    },
    'unRegisterListener': function unRegisterListener() {
        console.warn('this message from default bridge! there is noting happening here!!');
    },
    'prepareSwitchPage': function prepareSwitchPage() {
        console.warn('this message from default bridge! there is noting happening here!!');
    },
    'onPageLoaded': function onPageLoaded() {
        console.warn('this message from default bridge! there is noting happening here!!');
    },
    'onMainLoaded': function onMainLoaded() {
        console.warn('this message from default bridge! there is noting happening here!!');
    }
};

var _arguments$1 = arguments;
var _this = window;

var baseReg = /^.*?(?=[^\/]*(\?|$))/;
var absoluteReg = /^(\w+:\/\/|\/)/;
var onlineReg = /^((http|https):\/\/|\/)/;

var urlUtils = {
    getBase: function getBase(url) {
        return url ? baseReg.exec(url)[0] : '';
    },
    isAbsolute: function isAbsolute(url) {
        return absoluteReg.test(url);
    },
    isHttpAddress: function isHttpAddress(url) {
        return onlineReg.test(url);
    },
    resolve: function resolve(base, url) {
        if (_arguments$1.length === 1) {
            url = base;
            base = urlUtils.getBaseLocationUrl();
        }
        return urlUtils.isAbsolute(url) ? url : base + '/' + url;
    },
    getBaseLocationUrl: function getBaseLocationUrl() {
        var url = urlUtils.getBase(location.href);
        urlUtils.getBaseLocationUrl = function () {
            return url;
        };
        return _this.getBaseLocationUrl();
    }
};

var running = false;

var MidwayConfig = {
    BasePath: '',
    RunEnvironment: 'product',
    ConfigPath: 'configuration',
    JsLibraryPath: 'js-library',
    BundlePath: 'presenters',
    Terminal: 'none',
    Runtime: 'web',
    PlayerReleaseNumber: '000000',
    NativeInterface: undefined,
    NativeBridgeClass: undefined
};

var Midway = {};

Object.defineProperty(Midway, 'version', {
    value: "1.5.7"
});

Object.defineProperty(Midway, 'config', {
    value: function value(options) {
        if (supportFunction.hasProp(Midway, 'hasReady')) {
            console.error("The container has been initialized and can not be modified");
            return;
        }

        if (options.BundlePath !== undefined && typeof options.BundlePath === 'string') {
            MidwayConfig.BundlePath = options.BundlePath;
        }
        if (options.BasePath !== undefined && typeof options.BasePath === 'string') {
            MidwayConfig.BasePath = options.BasePath;
        }
        if (options.ConfigPath !== undefined && typeof options.ConfigPath === 'string') {
            MidwayConfig.ConfigPath = options.ConfigPath;
        }
        if (options.RunEnvironment !== undefined && typeof options.RunEnvironment === 'string') {
            if (options.RunEnvironment === 'product' || options.RunEnvironment === 'development') {
                MidwayConfig.RunEnvironment = options.RunEnvironment;
            }
        }
        if (options.Extra !== undefined && _typeof(options.Extra) === "object") {
            MidwayConfig.Extra = options.Extra;
        }
        //如果BasePath包含HTTP或HTTPS则认为是在线场景
        Object.defineProperty(MidwayConfig, 'Online', { value: urlUtils.isHttpAddress(MidwayConfig.BasePath) });
        //配置运行时
        var runtimeMapping = options.RuntimeMapping || { 'AndroidInterface': 'mobile', 'iOSInterface': 'mobile', 'PCInterface': 'pc' };
        for (var key in runtimeMapping) {
            if (key in window) {
                MidwayConfig.Runtime = runtimeMapping[key] || 'web';
                MidwayConfig.NativeInterface = key;
                MidwayConfig.NativeBridgeClass = options.NativeBridgeClass || "IcrJsBridge";
                break;
            }
        }
        //配置教师与学生端
        var terminal = 'none';
        if (requestParams.params['terminal']) {
            terminal = requestParams.params['terminal'].toLowerCase();
        }
        MidwayConfig.Terminal = terminal;
    }
});

Object.defineProperty(Midway, 'runMidway', {
    value: function value(options) {
        if (running) {
            return;
        }
        //开始执行预加载过程
        running = true;
        var file = options && options.file ? options.file : "config.json";
        var code = options && options.code ? options.code : undefined;
        var version = options && options.version ? options.version : undefined;
        //配置原生桥接层
        if (MidwayConfig.Runtime !== 'web' && MidwayConfig.NativeInterface !== undefined) {
            var bridge = new NativeEventBridge(window[MidwayConfig.NativeInterface]);
            window.Bridge = bridge;
            if (requestParams.params['iframeBridge'] === 'true' && _typeof(window.top)) {
                window.top.Bridge = bridge;
            }
        }

        return getPlayerConfig(MidwayConfig, code, version, file).then(function (config) {
            //构建Bundle配置
            var preLoader = new PreLoader();
            //预加载完成后
            return preLoader.load(config).done(function () {
                //在Midway中设置一个已经准备完毕的标识
                Object.defineProperty(Midway, 'hasReady', { value: true });
                Object.defineProperty(Midway, 'Settings', { value: MidwayConfig });
                Object.freeze(MidwayConfig);
                console.log("Preload Over");
            });
        }).fail(function () {
            console.error("Unable to read the online player's configuration file");
        });
    }
});

Object.defineProperty(Midway, 'MidwayModule', { value: MidwayModule });

Object.defineProperty(Midway, 'FixPropertyConfig', { value: FixPropertyConfig });

Object.defineProperty(Midway, 'Bundle', { value: Bundle });

function MidwayModule(options) {
    var _options$code = options.code,
        code = _options$code === undefined ? options.code : _options$code,
        _options$template = options.template,
        template = _options$template === undefined ? options.template || undefined : _options$template,
        _options$style = options.style,
        style = _options$style === undefined ? options.style || undefined : _options$style,
        _options$dependLibs = options.dependLibs,
        dependLibs = _options$dependLibs === undefined ? options.dependLibs || [] : _options$dependLibs;
    //Bundle的名称不能为空

    assert(code === undefined, 'the module name is empty!');
    var styleValid = style !== undefined,
        templateValid = template !== undefined;
    var element = void 0;
    if (templateValid === true) {
        //检查模板
        element = jQuery.parseHTML(template);
        if (element.length > 1) {
            console.warn('component template can only one root element, but got ' + element.length);
            templateValid = false;
        }
    }
    if (styleValid && typeof style.toString !== 'function') {
        console.warn('component style not valid, please check it!');
        styleValid = false;
    }

    return function (module) {
        Object.defineProperty(module.prototype, '__dependLibs', { value: dependLibs });
        Object.defineProperty(module.prototype, '__code', { value: code });
        //允许组件没有模板
        if (templateValid) {
            Object.defineProperty(module.prototype, '__template', { value: element[0] });
        }
        //允许组件没有样式
        if (styleValid) {
            Object.defineProperty(module.prototype, '__style', { value: style });
        }
        //将target添加到管理对象中
        moduleManager.add(code, module);
    };
}

function FixPropertyConfig(options) {
    var _options$configurable = options.configurable,
        configurable = _options$configurable === undefined ? options.configurable || false : _options$configurable,
        _options$writable = options.writable,
        writable = _options$writable === undefined ? options.writable || false : _options$writable,
        _options$enumerable = options.enumerable,
        enumerable = _options$enumerable === undefined ? options.enumerable || false : _options$enumerable;


    return function (target, key, descriptor) {
        descriptor.configurable = configurable;
        descriptor.writable = writable;
        descriptor.enumerable = enumerable;
        return descriptor;
    };
}

(function (self) {

    arrayPolyFill();
    stringPolyFill();
    DOMPolyFill();

    if (!self.Midway) self.Midway = Midway;
})(typeof self !== 'undefined' ? self : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : window);

})));
